home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
3D GFX
/
3D GFX.iso
/
amiutils
/
i_l
/
irit5
/
irit
/
inptevl2.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-12-30
|
27KB
|
785 lines
/*****************************************************************************
* "Irit" - the 3d (not only polygonal) solid modeller. *
* *
* Written by: Gershon Elber Ver 0.2, Mar. 1990 *
******************************************************************************
* Module to evaluate the binary tree generated by the InptPrsr module. *
* All the objects are handled the same but the numerical one, which is *
* moved as a RealType and not as an object (only internally within this *
* module) as it is frequently used and consumes much less memory this way. *
* Note this module is par of InptPrsr module and was splited only because *
* of text file sizes problems... *
*****************************************************************************/
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#include "program.h"
#include "allocate.h"
#include "attribut.h"
#include "convex.h"
#include "ctrl-brk.h"
#include "dosintr.h"
#include "freeform.h"
#include "geomat3d.h"
#include "geomvals.h"
#include "inptprsg.h"
#include "inptprsl.h"
#include "objects.h"
#include "overload.h"
#include "primitiv.h"
#include "windows.h"
#include "iritgrap.h"
InptPrsrEvalErrType
IPGlblEvalError = IPE_NO_ERR; /* Global used by EvalTree. */
static void LocalPrintTree(ParseTree *Root, int Level, char *Str);
/*****************************************************************************
* DESCRIPTION: M
* Returns a string representing the given type. M
* *
* PARAMETERS: M
* Type: Type to get a string representation for. M
* *
* RETURN VALUE: M
* char *: A string describing type Type. M
* *
* KEYWORDS: M
* InptPrsrTypeToStr M
*****************************************************************************/
char *InptPrsrTypeToStr(IritExprType Type)
{
switch (Type) {
case POLY_EXPR:
return "Poly";
case NUMERIC_EXPR:
return "Numeric";
case POINT_EXPR:
return "Point";
case VECTOR_EXPR:
return "Vector";
case PLANE_EXPR:
return "Plane";
case CTLPT_EXPR:
return "Control Point";
case MATRIX_EXPR:
return "Matrix";
case STRING_EXPR:
return "String";
case OLST_EXPR:
return "List Object";
case CURVE_EXPR:
return "Curve";
case SURFACE_EXPR:
return "Surface";
default:
return "Undefined";
}
}
/*****************************************************************************
* DESCRIPTION: M
* Counts the number of parameters in Root. Parameters are defined as M
* subtrees seperated by commas, i.e.: the infix form 1, 2, 3, 4 is M
* represented as [1, [2, [3, 4]]] in the tree supplied to this function and M
* 4 (number of parameters) is returned. M
* *
* PARAMETERS: M
* Root: To count the number of its parameters. M
* *
* RETURN VALUE: M
* int: Number of parameters encountered. M
* *
* KEYWORDS: M
* InptEvalCountNumParameters M
*****************************************************************************/
int InptEvalCountNumParameters(ParseTree *Root)
{
int i = 1;
if (Root == NULL)
return 0;
while (Root -> NodeKind == COMMA) {
i++;
Root = Root -> Right;
}
return i;
}
/*****************************************************************************
* DESCRIPTION: M
* Fetches the i'th paramter out of a tree represent n parameters M
* (0 <= i < n). See InptEvalCountNumParameters for more description of M
* structure. M
* Note it is assumed the tree HAS n parameters and 0<=i<n (No input error). M
* *
* PARAMETERS: M
* Root: To fetch its i'th parameter. M
* i: The parameter wanted. M
* n: Total number of parameters in Root. M
* *
* RETURN VALUE: M
* ParseTree *: The requested parameter. M
* *
* KEYWORDS: M
* InptEvalFetchParameter M
*****************************************************************************/
ParseTree *InptEvalFetchParameter(ParseTree *Root, int i, int n)
{
int j;
for (j = 0; j < i; j++)
Root = Root -> Right;
if (i == n - 1)
return Root;
else
return Root -> Left;
}
/*****************************************************************************
* DESCRIPTION: M
* Fetches the parameters of a function from the parsed tree. M
* Returns TRUE iff fetching was succesfull. M
* *
* PARAMETERS: M
* Root: Where the parameters should be searched for. M
* FuncTable: The table's entry of the function we deal with. M
* NumParams: Number of parameters of function. M
* Level: Level of recursion. To identify top levels. M
* Params: Where to put the parameters as ParseTree. M
* ParamPtrs: And as pointers to RealType/PointType/VectorType etc. M
* *
* RETURN VALUE: M
* int: If everything matches. M
* *
* KEYWORDS: M
* InptEvalFetchParameters M
*****************************************************************************/
int InptEvalFetchParameters(ParseTree *Root,
FuncTableType *FuncTable,
int NumParams,
int Level,
ParseTree *Params[],
VoidPtr ParamPtrs[])
{
int i;
Level++;
for (i = 0; i < NumParams; i++) {
if ((Params[i] = InptPrsrEvalTree(InptEvalFetchParameter(Root -> Right,
i, NumParams),
Level)) == NULL)
return i;
if (FuncTable != NULL) {
if (FuncTable -> ParamObjType[i] == NUMERIC_EXPR)
ParamPtrs[i] = &Params[i] -> PObj -> U.R;
else if (FuncTable -> ParamObjType[i] == POINT_EXPR)
ParamPtrs[i] = Params[i] -> PObj -> U.Pt;
else if (FuncTable -> ParamObjType[i] == VECTOR_EXPR)
ParamPtrs[i] = Params[i] -> PObj -> U.Vec;
else if (FuncTable -> ParamObjType[i] == CTLPT_EXPR)
ParamPtrs[i] = &Params[i] -> PObj -> U.CtlPt;
else if (FuncTable -> ParamObjType[i] == PLANE_EXPR)
ParamPtrs[i] = Params[i] -> PObj -> U.Plane;
else if (FuncTable -> ParamObjType[i] == STRING_EXPR)
ParamPtrs[i] = Params[i] -> PObj -> U.Str;
else
ParamPtrs[i] = Params[i] -> PObj;
}
}
return i;
}
/*****************************************************************************
* DESCRIPTION: M
* Tests number of parameters and type of them against what is defined in the M
* global tables Num/Obj/GenFuncTable. return TRUE if mismatch was detected. M
* *
* PARAMETERS: M
* Root: The function entry node. M
* *
* RETURN VALUE: M
* int: TRUE if a mismatch wasdetected, FALSE of o.k. N
* *
* KEYWORDS: M
* IritEvalFuncParamMismatch M
*****************************************************************************/
int IritEvalFuncParamMismatch(ParseTree *Root)
{
int FuncOffset, Count,
i = Root -> NodeKind / 100;
FuncTableType *FuncTable;
switch (i * 100) {
case NUM_FUNC: /* Numeric (real returned) functions. */
FuncOffset = Root -> NodeKind - NUM_FUNC_OFFSET;
FuncTable = (FuncTableType *) NumFuncTable;
break;
case OBJ_FUNC1: /* Object (returned) functions. */
case OBJ_FUNC2: /* Object (returned) functions. */
FuncOffset = Root -> NodeKind - OBJ_FUNC_OFFSET;
FuncTable = (FuncTableType *) ObjFuncTable;
break;
case GEN_FUNC:
FuncOffset = Root -> NodeKind - GEN_FUNC_OFFSET;
FuncTable = (FuncTableType *) GenFuncTable;
break;
default:
IPGlblEvalError = IE_ERR_FATAL_ERROR;
UpdateCharError("Undefined function - ", Root -> NodeKind, Root);
return TRUE;
}
Count = InptEvalCountNumParameters(Root -> Right);
if (FuncTable[FuncOffset].NumOfParam == ANY_PARAM_NUM) {
for (i = 0; i < Count; i++) {
IritExprType EType;
/* Special cases - FORLOOP and IF - top level considerations. */
if ((Root -> NodeKind == FORLOOP && i == 3) ||
(Root -> NodeKind == IFCOND && i > 0))
EType = InptPrsrTypeCheck(InptEvalFetchParameter(Root -> Right,
i, Count), 0);
else
EType = InptPrsrTypeCheck(InptEvalFetchParameter(Root -> Right,
i, Count), 1);
/* Check only for consistency of input. */
if (EType == ERROR_EXPR)
return TRUE;
}
return FALSE;
}
else { /* Number of parameter is well known and is in Count. */
/* See if number of parameters is ok: */
if (Count != FuncTable[FuncOffset].NumOfParam) {
IPGlblEvalError = IE_ERR_NUM_PRM_MISMATCH;
sprintf(IPGlblCharData, "Func %s - %d expected, %d found",
FuncTable[FuncOffset].FuncName,
FuncTable[FuncOffset].NumOfParam,
Count);
return TRUE;
}
/* See if type of parameters are consistent: */
for (i = 0; i < Count; i++) {
IritExprType EType;
/* Special cases - FORLOOP and IF - top level considerations. */
if ((Root -> NodeKind == FORLOOP && i == 3) ||
(Root -> NodeKind == IFCOND && i > 0))
EType = InptPrsrTypeCheck(InptEvalFetchParameter(Root -> Right,
i, Count), 0);
else
EType = InptPrsrTypeCheck(InptEvalFetchParameter(Root -> Right,
i, Count), 1);
if (EType == ERROR_EXPR)
return TRUE;
if (FuncTable[FuncOffset].ParamObjType[i] != ANY_EXPR &&
!(FuncTable[FuncOffset].ParamObjType[i] & EType)) {
sprintf(IPGlblCharData, "Func %s,%sparameter %d",
FuncTable[FuncOffset].FuncName,
IPGlblEvalError == IE_ERR_IP_OBJ_UNDEFINED ?
" undefined " : " ", i + 1);
IPGlblEvalError = IE_ERR_TYPE_MISMATCH;
return TRUE;
}
}
return FALSE;
}
}
/*****************************************************************************
* DESCRIPTION: M
* Deallocates a parsed tree - release all memory allocated by it. M
* *
* PARAMETERS: M
* Root: Of tree to release. M
* *
* RETURN VALUE: M
* void M
* *
* KEYWORDS: M
* InptPrsrFreeTree M
*****************************************************************************/
void InptPrsrFreeTree(ParseTree *Root)
{
char s[LINE_LEN];
if (!Root)
return;
if (IS_FUNCTION(Root -> NodeKind)) {
if (IS_NO_PARAM_FUNC(Root -> NodeKind))
ExprFree(Root);
else {
InptPrsrFreeTree(Root -> Right);
if (Root -> PObj != NULL && strlen(Root -> PObj -> Name) == 0)
IPFreeObject(Root -> PObj); /* Its temp.*/
ExprFree(Root);
}
return;
}
switch (Root -> NodeKind) {
case DIV:
case MINUS:
case MULT:
case PLUS:
case POWER:
InptPrsrFreeTree(Root -> Right);
InptPrsrFreeTree(Root -> Left);
if (Root -> PObj != NULL && strlen(Root -> PObj -> Name) == 0)
IPFreeObject(Root -> PObj); /* Its tmp. */
ExprFree(Root);
break;
case UNARMINUS:
case BOOL_NOT:
InptPrsrFreeTree(Root -> Right);
if (Root -> PObj != NULL && strlen(Root -> PObj -> Name) == 0)
IPFreeObject(Root -> PObj); /* Its tmp. */
ExprFree(Root);
break;
case COMMA:
case COLON:
case EQUAL:
case CMP_EQUAL:
case CMP_NOTEQUAL:
case CMP_LSEQUAL:
case CMP_GTEQUAL:
case CMP_LESS:
case CMP_GREAT:
case BOOL_OR:
case BOOL_AND:
InptPrsrFreeTree(Root -> Right);
InptPrsrFreeTree(Root -> Left);
ExprFree(Root);
break;
case PARAMETER:
if (Root -> PObj) {
/* If object is not part of global variable list - remove it.*/
if (strlen(Root -> PObj -> Name) == 0)
IPFreeObject(Root -> PObj);
else
Root -> PObj -> Count--;
}
ExprFree(Root);
break;
case NUMBER:
case STRING:
if (Root -> PObj)
IPFreeObject(Root -> PObj);
ExprFree(Root);
break;
case TOKENSTART:
ExprFree(Root);
break;
case OPENPARA:
case CLOSPARA:
ExprFree(Root);
break;
default:
/* We might free partially build (by InptPrsr) tree when error */
/* is detected, and such tree may have nodes with NodeKind>=1000.*/
if (Root -> NodeKind >= 1000) {
ExprFree(Root);
}
else {
sprintf(s, "%s (%d).\n",
"InptPrsrFreeTree: Undefined ParseTree type to free",
Root -> NodeKind);
IritFatalError(s);
}
break;
}
}
/*****************************************************************************
* DESCRIPTION: M
* Prints the content of ROOT (using inorder traversal). M
* If *Str = NULL prints on stderr, else on given string Str. *
* *
* PARAMETERS: M
* Root: Of tree to print. M
* Str: String to write on the inorder of Root, or stderr if NULL. M
* *
* RETURN VALUE: M
* void M
* *
* KEYWORDS: M
* InptPrsrPrintTree M
*****************************************************************************/
void InptPrsrPrintTree(ParseTree *Root, char *Str)
{
strcpy(IPGlblCharData, ""); /* Make the string empty. */
if (Str == NULL) {
strcpy(IPGlblCharData, ""); /* Make the string empty. */
LocalPrintTree(Root, 0, IPGlblCharData); /* Copy to local str. */
fprintf(stderr, IPGlblCharData); /* and print... */
}
else {
strcpy(Str, ""); /* Make the string empty. */
LocalPrintTree(Root, 0, Str); /* Dont print to stderr - copy to str. */
}
}
/*****************************************************************************
* DESCRIPTION: *
* Auxiliary function of InptPrsrPrintTree. *
* It is assumed Str has at least INPUT_LINE_LEN places to write the *
* expression. *
* *
* PARAMETERS: *
* Root: Of tree to print. *
* Level: Of recursion. *
* Str: String to write on the inorder of Root, or stderr if NULL. *
* *
* RETURN VALUE: *
* void *
*****************************************************************************/
static void LocalPrintTree(ParseTree *Root, int Level, char *Str)
{
int Len, i,
CloseFlag = FALSE;
if (!Root)
return;
i = Root -> NodeKind / 100;
if ((Len = strlen(Str)) > INPUT_LINE_LEN + 100) /* Prevent overflow. */
if (Str[Len - 1] == '.')
return; /* "..." was allready concatenated. */
else {
strcat(Str, "...");
return;
}
# ifdef DEBUG1
strcat(Str, "["); /* Usefull to see ALL nestings - no preceedings. */
# endif /* DEBUG1 */
switch (i * 100) {
case USER_FUNC:
switch (Root -> NodeKind) {
case USERFUNCDEF:
Level = 0;
CloseFlag = TRUE;
strcat(Str, "function(");
break;
case USERPROCDEF:
Level = 0;
CloseFlag = TRUE;
strcat(Str, "procedure(");
break;
case USERINSTDEF:
Level = 0;
CloseFlag = TRUE;
strcat(Str, Root -> UserFunc -> FuncName);
strcat(Str, "(");
break;
}
break;
case NUM_FUNC:
Level = 0;
CloseFlag = TRUE;
strcat(Str,
NumFuncTable[Root -> NodeKind - NUM_FUNC_OFFSET].FuncName);
strcat(Str, "(");
break;
case OBJ_FUNC1:
case OBJ_FUNC2:
Level = 0;
CloseFlag = TRUE;
strcat(Str,
ObjFuncTable[Root -> NodeKind - OBJ_FUNC_OFFSET].FuncName);
strcat(Str, "(");
break;
case GEN_FUNC:
Level = 0;
CloseFlag = TRUE;
strcat(Str,
GenFuncTable[Root -> NodeKind - GEN_FUNC_OFFSET].FuncName);
strcat(Str, "(");
break;
case OPERATORS:
switch (Root -> NodeKind) {
case DIV:
if (Level > 1) {
strcat(Str, "(");
CloseFlag = TRUE;
}
Level = 1; /* Div Level. */
LocalPrintTree(Root -> Left, Level, Str);
strcat(Str, "/");
break;
case MINUS:
if (Level > 0) {
strcat(Str, "(");
CloseFlag = TRUE;
}
Level = 0; /* Minus Level. */
LocalPrintTree(Root -> Left, Level, Str);
strcat(Str, "-");
break;
case MULT:
if (Level > 1) {
strcat(Str, "(");
CloseFlag = TRUE;
}
Level = 1; /* Mul Level. */
LocalPrintTree(Root -> Left, Level, Str);
strcat(Str, "*");
break;
case PLUS:
if (Level > 0) {
strcat(Str, "(");
CloseFlag = TRUE;
}
Level = 0; /* Plus Level. */
LocalPrintTree(Root -> Left, Level, Str);
strcat(Str, "+");
break;
case POWER:
Level = 2; /* Power Level. */
LocalPrintTree(Root -> Left, Level, Str);
strcat(Str, "^");
break;
case UNARMINUS:
strcat(Str, "(-");
Level = 0;
CloseFlag = TRUE;
break;
case COMMA:
LocalPrintTree(Root -> Left, Level, Str);
strcat(Str, ",");
break;
case COLON:
LocalPrintTree(Root -> Left, Level, Str);
strcat(Str, ":");
break;
case EQUAL:
LocalPrintTree(Root -> Left, Level, Str);
strcat(Str, "=");
break;
case CMP_EQUAL:
LocalPrintTree(Root -> Left, Level, Str);
strcat(Str, "==");
break;
case CMP_NOTEQUAL:
LocalPrintTree(Root -> Left, Level, Str);
strcat(Str, "!=");
break;
case CMP_LSEQUAL:
LocalPrintTree(Root -> Left, Level, Str);
strcat(Str, "<=");
break;
case CMP_GTEQUAL:
LocalPrintTree(Root -> Left, Level, Str);
strcat(Str, ">=");
break;
case CMP_LESS:
LocalPrintTree(Root -> Left, Level, Str);
strcat(Str, "<");
break;
case CMP_GREAT:
LocalPrintTree(Root -> Left, Level, Str);
strcat(Str, ">");
break;
case BOOL_OR:
LocalPrintTree(Root -> Left, Level, Str);
strcat(Str, "||");
break;
case BOOL_AND:
LocalPrintTree(Root -> Left, Level, Str);
strcat(Str, "&&");
break;
case BOOL_NOT:
LocalPrintTree(Root -> Left, Level, Str);
strcat(Str, "!");
break;
case NUMBER:
sprintf(&Str[strlen(Str)], "%g", Root -> PObj -> U.R);
break;
case PARAMETER:
sprintf(&Str[strlen(Str)], "%s", Root -> PObj -> Name);
break;
case STRING:
sprintf(&Str[strlen(Str)], "\"%s\"",
Root -> PObj -> U.Str);
break;
case OPENPARA:
strcat(Str, "(");
break;
case CLOSPARA:
strcat(Str, ")");
break;
case TOKENSTART:
break;
default:
IritFatalError("LocalPrintTree: Undefined ParseTree type to print, exit");
}
break;
default:
IritFatalError("LocalPrintTree: Undefined ParseTree type to print, exit");
}
LocalPrintTree(Root -> Right, Level, Str);
if (CloseFlag)
strcat(Str, ")");
# ifdef DEBUG1
strcat(Str, "]"); /* Usefull to see ALL nestings - no preceedings. */
# endif /* DEBUG1 */
}
/*****************************************************************************
* DESCRIPTION: M
* Duplicates a parse tree - Generates brand new ParseTree structure but M
* binds to non-temp variables if they are exists - their Name is not NULL. M
* This means that updating these objects in the copied tree, will affect M
* these objects in the original tree. M
* *
* PARAMETERS: M
* Root: To duplicate. M
* *
* RETURN VALUE: M
* ParseTree *: Duplicated parse tree M
* *
* KEYWORDS: M
* InptPrsrCopyTree M
*****************************************************************************/
ParseTree *InptPrsrCopyTree(ParseTree *Root)
{
ParseTree *NewRoot;
if (Root == NULL)
return NULL;
NewRoot = ExprMalloc();
if (IS_FUNCTION(Root -> NodeKind)) { /* All the functions. */
NewRoot -> NodeKind = Root -> NodeKind;
NewRoot -> Right = InptPrsrCopyTree(Root -> Right);
if (IS_USER_FUNCTION(Root -> NodeKind))
NewRoot -> UserFunc = Root -> UserFunc;
return NewRoot;
}
switch (Root -> NodeKind) {
case DIV:
case MINUS:
case MULT:
case PLUS:
case POWER:
case COMMA:
case COLON:
case EQUAL:
case CMP_EQUAL:
case CMP_NOTEQUAL:
case CMP_LSEQUAL:
case CMP_GTEQUAL:
case CMP_LESS:
case CMP_GREAT:
case BOOL_OR:
case BOOL_AND:
NewRoot -> NodeKind = Root -> NodeKind;
NewRoot -> Right = InptPrsrCopyTree(Root -> Right);
NewRoot -> Left = InptPrsrCopyTree(Root -> Left);
return NewRoot;
case UNARMINUS:
case BOOL_NOT:
NewRoot -> NodeKind = Root -> NodeKind;
NewRoot -> Right = InptPrsrCopyTree(Root -> Right);
NewRoot -> Left = NULL;
return NewRoot;
case NUMBER:
case PARAMETER:
case STRING:
NewRoot -> NodeKind = Root -> NodeKind;
NewRoot -> PObj = Root -> PObj; /* Point on SAME object. */
NewRoot -> PObj -> Count++; /* But increase its ref. count. */
return NewRoot;
case TOKENSTART:
NewRoot -> NodeKind = Root -> NodeKind;
return NewRoot;
default:
IritFatalError("InptPrsrCopyTree: Undefined ParseTree type to copy, exit");
}
return NULL; /* Makes warning silent. */
}
/*****************************************************************************
* DESCRIPTION: M
* Routine to return evaluation error if happen one, zero elsewhere M
* *
* PARAMETERS: M
* Message: Place here a message describing an error, if was one. M
* *
* RETURN VALUE: M
* InptPrsrEvalErrType: Type of evaluation error. M
* *
* KEYWORDS: M
* InptPrsrEvalError M
*****************************************************************************/
InptPrsrEvalErrType InptPrsrEvalError(char **Message)
{
InptPrsrEvalErrType Temp;
*Message = IPGlblCharData;
Temp = IPGlblEvalError;
IPGlblEvalError = IPE_NO_ERR;
return Temp;
}